﻿#ifndef FCABSTRACTNODE_H
#define FCABSTRACTNODE_H
#include <memory>
#include "FCDataPackage.h"
#include "FCNodeMetaData.h"

class FCAbstractNodeGraphicsItem;

FC_IMPL_FORWARD_DECL(FCAbstractNode)

/**
 * @brief 节点对应的基类
 *
 * 节点可以理解为一个函数，函数有多个输入，但只会有一个return或者多个分支的return，
 * 反映到节点中就是可以存在多个输入，但也应该有多个输出（参考流程中的菱形控制（if-else））。
 * 因此节点的输入点是0~n，节点的输出点是0~n。
 *
 *
 *
 * 需要用户实现以下6个函数
 * @code
 * //获取所有输入的参数名
 * virtual QList<QString> getInputKeys() const = 0;
 * //获取所有输出的参数名
 * virtual QList<QString> getOutputKeys() const = 0;
 * //节点对应的item显示接口，所有node都需要提供一个供前端的显示接口
 * virtual FCAbstractNodeGraphicsItem *createGraphicsItem();
 * //输出参数
 * virtual FCDataPackage output(const QString& ouputkey) = 0;
 * @endcode
 *
 *
 *
 */

class FCNODE_API FCAbstractNode : public std::enable_shared_from_this<FCAbstractNode>
{
    FC_IMPL(FCAbstractNode)
    friend class FCAbstractNodeGraphicsItem;
public:
    enum NodeAction {
        NodeInputed ///< 节点有输入完成，调用input方法会触发此动作,传递的value为input的值
    };

    typedef std::shared_ptr<FCAbstractNode> Pointer;
    FCAbstractNode();
    virtual ~FCAbstractNode();


    //获取node的名字
    QString getNodeName() const;
    void setNodeName(const QString& name);

    //获取node的类型，这个类型可以表征同一类型的node 这个不会进行翻译
    QString getNodePrototype() const;

    //获取图标，图标是节点对应的图标
    QIcon getIcon() const;
    void setIcon(const QIcon& icon);

    //获取节点的元数据
    const FCNodeMetaData& metaData() const;
    FCNodeMetaData& metaData();

    //设置元数据
    void setMetaData(const FCNodeMetaData& metadata);

    //返回自身智能指针
    Pointer pointer();

public://连接相关
    //获取所有输入的参数名
    virtual QList<QString> getInputKeys() const = 0;

    //获取所有输出的参数名
    virtual QList<QString> getOutputKeys() const = 0;

    //建立连接,如果基础的对象需要校验，可继承此函数
    virtual bool linkTo(const QString& outpt, Pointer toItem, const QString& inpt);

    //移除连接,把输出节点对应的连接解除
    bool detachToLink(const QString& outpt);

public:
    //节点对应的item显示接口，所有node都需要提供一个供前端的显示接口
    virtual FCAbstractNodeGraphicsItem *createGraphicsItem() = 0;

    //获取node对应的item
    FCAbstractNodeGraphicsItem *graphicsItem();

    //获取node对应的item
    const FCAbstractNodeGraphicsItem *graphicsItem() const;

public:
    //数据操作
    //输入参数
    void input(const QString& key, FCDataPackage dp);

    //获取input的数据包,此函数返回的FCDataPackage是引用，不发生拷贝，修改将直接改变input所维护的FCDataPackage内容
    FCDataPackage inputData(const QString& key);

    //输出参数
    virtual FCDataPackage output(const QString& ouputkey) = 0;

protected:
    //注册item，node的几个生命周期将会反馈到item中，destory
    void registGraphicsItem(FCAbstractNodeGraphicsItem *item);

    //调用此函数，将会在
    void callItemNodeHasAction(NodeAction act, const QVariant& v);
};

#endif // FCABSTRACTNODE_H
